/**
 * 
 */
package com.shiplanet.util;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.CropImageFilter;
import java.awt.image.FilteredImageSource;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import org.apache.log4j.Logger;

/**
 * @author joesong
 *
 */

public class ImageProcessor {
	private static BufferedImage iconImage = null;
	private static Logger logger = Logger.getLogger("ImageProcessor");

	private BufferedImage bufferedImage;

	public ImageProcessor(File imageFile) throws IOException {

		// Sets a flag indicating whether a disk-based cache file should be used
		// when creating ImageInputStreams and ImageOutputStreams.
		// When reading from a standard InputStream, it may be necessary to save
		// previously read information in a cache since the underlying stream
		// does not allow data to be re-read. Similarly, when writing to a
		// standard OutputStream, a cache may be used to allow a previously
		// written value to be changed before flushing it to the final
		// destination.

		// The cache may reside in main memory or on disk. Setting this flag to
		// false disallows the use of disk for future streams, which may be
		// advantageous when working with small images, as the overhead of
		// creating and destroying files is removed.

		// On startup, the value is set to true.
		ImageIO.setUseCache(false);

		this.bufferedImage = ImageIO.read(imageFile);

	}

	public ImageProcessor(BufferedImage bufferedImage) {

		this.bufferedImage = bufferedImage;

	}

	/**
	 * Save the image buffer to a file
	 * 
	 * @param targetFileName
	 * @throws Exception
	 */
	public void saveImageAs(String targetFileName) throws IOException {

		logger.debug("save image as " + targetFileName);

		ImageIO.write(bufferedImage, "jpg", new File(targetFileName));

	}

	/**
	 * Zoom the image file to a new dimension no larger than the designated
	 * width and height
	 * 
	 * @param targetFileName
	 *            the name of target file
	 * @param width
	 *            the width for target file
	 * @param height
	 *            the height for target file
	 * @throws Exception
	 */
	public ImageProcessor zoomOut(int width, int height) {
		logger.debug("zoom out image to " + width + " x " + height);

		BufferedImage dst = null;

		double ratioWidth = (double) width / bufferedImage.getWidth();
		double ratioHeight = (double) height / bufferedImage.getHeight();

		// scale the target to at least the dimension as parameters indicate
		double ratio = ratioWidth > ratioHeight ? ratioWidth : ratioHeight;

		AffineTransformOp op = new AffineTransformOp(
				AffineTransform.getScaleInstance(ratio, ratio),
				AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
		dst = op.filter(bufferedImage, null);

		CropImageFilter cropFilter = new CropImageFilter(dst.getWidth() / 2
				- width / 2, dst.getHeight() / 2 - height / 2, width,
				height);
		Image img = Toolkit.getDefaultToolkit().createImage(
				new FilteredImageSource(dst.getSource(), cropFilter));
		BufferedImage tag = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);
		Graphics g = tag.getGraphics();
		g.drawImage(img, 0, 0, null); // 绘制缩小后的图
		g.dispose();

		return new ImageProcessor(tag);
	}

	/**
	 * add text water mark
	 * 
	 * @param text
	 * @return
	 * @throws Exception
	 */
	public ImageProcessor textWaterMark(String text) throws Exception {

		logger.debug("add text water mark");

		// 得到源图宽
		int width = bufferedImage.getWidth(null);
		// 得到源图长
		int height = bufferedImage.getHeight(null);

		// 创建一个BufferedImage来作为图像操作容器
		BufferedImage dst = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);
		// 创建一个绘图环境来进行绘制图象
		Graphics2D g = dst.createGraphics();
		// 将原图像数据流载入这个BufferedImage
		g.drawImage(bufferedImage, 0, 0, width, height, null);
		// 设定文本字体
		g.setFont(new Font("Arial", Font.BOLD, 28));
		// 获取文本的大小
		Rectangle2D stringBounds = g.getFontMetrics().getStringBounds(text, g);
		// 设定文本颜色
		g.setColor(Color.white);
		// 设置透明度
		g.setComposite(AlphaComposite
				.getInstance(AlphaComposite.SRC_ATOP, 0.5f));
		// 向BufferedImage写入文本字符,水印在图片上的坐标
		g.drawString(text, width - (int) stringBounds.getWidth() - 10,
				height - 10);
		// 使更改生效
		g.dispose();

		return new ImageProcessor(dst);
	}

	/**
	 * add image water mark
	 * 
	 * @param iconImage
	 * @return
	 * @throws Exception
	 */
	public ImageProcessor imageWaterMark(String iconFilePath) throws Exception {

		logger.debug("add image water mark");

		// initiate the icon file that is used to water mark photos
		if (iconImage == null) {
			iconImage = ImageIO.read(new File(iconFilePath));
		}
		
		// 目标文件
		int width = bufferedImage.getWidth(null);
		int height = bufferedImage.getHeight(null);
		BufferedImage dst = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);
		Graphics2D g = dst.createGraphics();
		g.drawImage(bufferedImage, 0, 0, width, height, null);

		// 水印文件 路径
		int w_width = iconImage.getWidth(null);
		int w_height = iconImage.getHeight(null);
		g.setComposite(AlphaComposite
				.getInstance(AlphaComposite.SRC_ATOP, 0.5f));
		g.drawImage(iconImage, width - w_width, height - w_height, w_width,
				w_height, null);

		// 水印文件结束
		g.dispose();
		return new ImageProcessor(dst);
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			File file = new File("test.jpeg");
			ImageProcessor processor = new ImageProcessor(file);
//			processor.saveImageAs("testCopy.jpg");

			processor.zoomOut(100, 100).saveImageAs("testZoomTo.jpg");

//			processor.textWaterMark("Ship Trade Biz").saveImageAs(
//					"testTextWaterMark.jpg");

			  processor.imageWaterMark("icon.png").saveImageAs(
			  "testImageWaterMark.jpg");
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}
